package orm.spring;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import orm.base.BaseController;
import orm.base.BasePageInfo;
import orm.config.UnAuth;
import orm.utils.HttpUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 请求AOP拦截
 * Created by 汪超 on 2017/9/28.
 */
@Component
@Aspect
public class DispatcherServletAop extends BaseController implements Ordered {

//    private String[] withOutController = {"doLogin", "doLoginBackend", "login_page", "doRegister", "doQueryNormalChartRooms", "doGetUnLoginUser", "upload","doNoticeCourse"};


	@Pointcut("execution(* *.*.controller.*.*(..)) || execution(* *.controller.*.*(..)) || target(orm.base.Ex.BaseControllerEx)")
	public void doInit() {
	}


	@Around("doInit()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		//獲得Request對象
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

		Signature sig = joinPoint.getSignature();
		MethodSignature msig = null;
		if (!(sig instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		msig = (MethodSignature) sig;
//        Object target = joinPoint.getTarget();
		Method currentMethod = msig.getMethod();
//        Class<?> clazz = currentMethod.getDeclaringClass();
		//訪問完整目標方法路径
		String fullTargetPath = getFullTargetPath(joinPoint);
		//获得方法名
		String targetCls = sig.getName();
		Object o;
		// 过滤初始化seq res
		if (!targetCls.equals("setReqAndRes")) {
			//方法过滤 //类过滤 clazz.isAnnotationPresent(UnAuth.class)
			if (!currentMethod.isAnnotationPresent(UnAuth.class)) {
				String token = request.getParameter("token");
				if (token == null) {
//                    User user = (User) request.getSession().getAttribute("user");
//                    if(user == null) {
					HttpUtils.outJson(this.codeMess(login_eCode, "登录超时，请重新登录！").toJSONString());
//                        return "redirect:/user/login_page";
					return null;
//                    }
				} else {
					Object user = request.getSession().getAttribute("user-" + token);
					if (user == null) {
						HttpUtils.outJson(this.codeMess(login_eCode, "登录超时，请重新登录！").toJSONString());
						return null;
					}
				}
			}
			//log
			long sTime = new Date().getTime();
			//这里是执行的程序
			o = joinPoint.proceed();
			logger.info("正在請求 " + fullTargetPath + " 接口[請求耗時:" + (new Date().getTime() - sTime) + "ms]\n");
		} else {
			o = joinPoint.proceed();
		}
		if (o instanceof JSONObject) {
			HttpUtils.outJson(o.toString());
			return null;
		} else {
			return o;
		}
	}

	/**
	 * 优先级为最后
	 *
	 * @return
	 */
	@Override
	public int getOrder() {
		return 999;
	}

	/**
	 * 判断数组是否包含某个字符串
	 *
	 * @param strs
	 * @param s
	 * @return
	 */
	public static boolean isHave(String[] strs, String s) {
        /*
         * 此方法有两个参数，第一个是要查找的字符串数组，第二个是要查找的字符或字符串
		 */
		for (int i = 0; i < strs.length; i++) {
			if (strs[i].equals(s)) {// 循环查找字符串数组中的每个字符串中是否包含所有查找的内容
				return true;// 查找到了就返回真，不在继续查询
			}
		}
		return false;// 没找到返回false
	}

	/**
	 * 获得完整的目标路径
	 *
	 * @param joinPoint 切点
	 * @return
	 */
	public static String getFullTargetPath(ProceedingJoinPoint joinPoint) {
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method targetMethod = methodSignature.getMethod();
		return targetMethod.getDeclaringClass().getName() + "." + targetMethod.getName();
	}
}
